home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / pages < prev    next >
Encoding:
Text File  |  1997-08-26  |  5.1 KB  |  192 lines

  1. :
  2. # @(#) pages.sh 1.0 96/06/18
  3. # 92/09/05 John H. DuBois III (jhdiii@armory.com)
  4. # 92/09/26 Added help
  5. # 95/05/01 Use ranges lib
  6. # 96/06/18 Ported to 3.2v5 awk
  7.  
  8. Usage="$0 [-h] [-lines/page] page-ranges [file ...]"
  9.  
  10. case "$1" in
  11. -[0-9]*) LinesPerPage=$1; shift;;
  12. -h) echo \
  13. "$0: print selected pages.
  14. Usage: $Usage
  15.  
  16. If no file names are given, the standard input is read.
  17.  
  18. The input is grouped into pages and a selected subset of them is printed.
  19. Formfeeds are acted on correctly.
  20.  
  21. If the output device does automatic line wrap, lines that longer than
  22. the width of the output device will result in incorrect output.
  23. The first non-option argument is a list of pages to print.
  24.  
  25. Pages are given as a list of ranges separated by commas.
  26. A range is either one number, two numbers separted by a dash,
  27. or one number followed by a dash.  A range consisting of one
  28. number followed by a dash extends to the end of the document.
  29.  
  30. Options: 
  31. -n sets the number of lines per page to n.  The default is 66."
  32.     exit 0;;
  33. esac
  34.  
  35. if [ $# = 0 ]; then
  36.     echo \
  37. "No ranges given.  Usage: $Usage" 1>&2
  38.     exit 1
  39. fi
  40.  
  41. PageList=$1
  42. shift
  43.  
  44. /usr/bin/awk "
  45. BEGIN {
  46.     PageList = \"$PageList\"; LinesPerPage = substr(\"$LinesPerPage\""',2)
  47.     if (LinesPerPage == "")
  48.     LinesPerPage = 66
  49.     else
  50.     if (LinesPerPage !~ "[1-9][0-9]*")
  51.         ErrExit("Bad value for lines per page: " LinesPerPage)
  52.     LinesPerPage += 0    # Force to be a number so it will be compared that way
  53.     if ((Err = MakeRangeSet(PageList,Ranges)) != "")
  54.     ErrExit(Err)
  55.     NumRanges = Ranges["n"]
  56.  
  57.     RangeNum = LineNum = PageNum = 1
  58.     InRange = In(PageNum,Ranges["s",RangeNum],Ranges["e",RangeNum])
  59.     FS = "\014"
  60. }
  61.  
  62. # Ranges is a list of positive integer ranges in the form m-n,o-p,q,r-s...
  63. function MakeRangeSet(RangeSet,Ranges,
  64. RangeStrings,NumRanges,i,StartRange,EndRange,TmpRangeStarts,TmpRangeEnds,k) {
  65.     NumRanges = split(PageList,RangeStrings,",")
  66.     for (i = 1; i <= NumRanges; i++) {
  67.     if ((StartRange = EndRange = RangeStrings[i]) !~ \
  68.     "^[0-9]+(-([0-9]+)?)?$")
  69.         return "Bad range \"" StartRange "\""
  70.     sub("-.*","",StartRange)
  71.     sub(".*-","",EndRange)
  72.     # StartRange is now the starting value (if any) and
  73.     # EndRange is the ending value (if any).
  74.     if (EndRange == "")
  75.         EndRange = 2 ^ 30
  76.     if (StartRange == "")
  77.         StartRange = 1
  78.     # Force StartRange and EndRange to be numeric values
  79.     if ((StartRange !~ /^[1-9][0-9]*$/) || (EndRange !~ /^[1-9][0-9]*$/))
  80.         return "Invalid number in range " RangeStrings[i]
  81.     if (StartRange > EndRange)
  82.         return "Range start comes after range end in " RangeStrings[i]
  83.     # Store the rang for later sorting
  84.     TmpRangeStarts[i] = StartRange
  85.     TmpRangeEnds[i] = EndRange
  86.     }
  87.  
  88.     # Sort ranges
  89.     qsort(TmpRangeStarts,k)
  90.     Ranges["e",0] = 0
  91.  
  92.     # Save ranges in sorted order, and check for overlapping ranges.
  93.     for (i = 1; i <= NumRanges; i++) {
  94.     Ranges["e",i] = TmpRangeEnds[k[i]]
  95.     if ((Ranges["s",i] = TmpRangeStarts[k[i]]) <= Ranges["e",i - 1])
  96.         return \
  97.     "Overlapping ranges: " RangeStrings[k[i]] "," RangeStrings[k[i - 1]]
  98.     }
  99.     Ranges["n"] = NumRanges
  100.     return ""
  101. }
  102.  
  103. {
  104.     if (LineNum > LinesPerPage)
  105.     NewPage()
  106.     if (InRange)
  107.     printf "%s",$1
  108.     # Deal with formfeeds
  109.     for (i = 2; i <= NF; i++) {
  110.     if (InRange)
  111.         printf "\014"
  112.     NewPage()
  113.     if (InRange)
  114.         printf "%s",$i
  115.     }
  116.     if (InRange)
  117.     print ""
  118.     LineNum++
  119. }
  120.  
  121. function NewPage() {
  122.     PageNum++
  123.     LineNum = 1
  124.     # At the start of each page, check whether we are in a print range
  125.     WereInRange = InRange
  126.     InRange = In(PageNum,Ranges["s",RangeNum],Ranges["e",RangeNum])
  127.     # If last page was in range and we no longer are, move to next range
  128.     if (WereInRange && !InRange && ++RangeNum > NumRanges)
  129.     exit
  130. }
  131.  
  132. function In(a,Min,Max) {
  133.     return (Min <= a && a <= Max)
  134. }
  135.  
  136. function ErrExit(S) {
  137.     print S > "/dev/stderr"
  138.     Err = 1
  139.     exit 1
  140. }
  141.  
  142. # Arr is an array of values with arbitrary indices.
  143. # Array k is returned with numeric indices 1..n.
  144. # The values in k are the indices of array arr, 
  145. # ordered so that if array arr is stepped through
  146. # in the order arr[k[1]] .. arr[k[n]], it will be stepped
  147. # through in order of the values of its elements.
  148. # The return value is the number of elements in the array (n).
  149. function qsort(arr,k,  ArrInd,end) {
  150.     end = 0
  151.     for (ArrInd in arr)
  152.     k[++end] = ArrInd;
  153.     qsortseg(arr,k,1,end);
  154.     return end
  155. }
  156.  
  157. function qsortseg(arr,k,start,end,  left,right,sepval,tmp,tmpe,tmps) {
  158.     # handle two-element case explicitly for a tiny speedup
  159.     if ((end - start) == 1) {
  160.     if (arr[tmps = k[start]] > arr[tmpe = k[end]]) {
  161.         k[start] = tmpe
  162.         k[end] = tmps
  163.     }
  164.     return
  165.     }
  166.     left = start;
  167.     right = end;
  168.     sepval = arr[k[int((left + right) / 2)]]
  169.     # Make every element <= sepval be to the left of every element > sepval
  170.     while (left < right) {
  171.     while (arr[k[left]] < sepval)
  172.         left++
  173.     while (arr[k[right]] > sepval)
  174.         right--
  175.     if (left < right) {
  176.         tmp = k[left]
  177.         k[left++] = k[right]
  178.         k[right--] = tmp 
  179.     }
  180.     }
  181.     if (left == right)
  182.     if (arr[k[left]] < sepval)
  183.         left++
  184.     else
  185.         right--
  186.     if (start < right)
  187.     qsortseg(arr,k,start,right)
  188.     if (left < end)
  189.     qsortseg(arr,k,left,end)
  190. }
  191. ' "$@"
  192.